#pragma once

#include <iostream>
#include <string>
#include <functional>
#include "InetAddr.hpp"
// 把所有的文件描述符进行封装

// 未来，一个fd被读取连接成功后，就会为他创建一个Connection对象
// 然后，未来该fd读取到的所有数据，就应该被拼接到自己的inbuffer缓冲区里
// 这样每一个fd都有一组自己的in，out的应用层缓冲区，这样，一个fd上的数据如果没有读到完整报文也不影响
// 因为可以暂存在自己的buffer里，等到下次读，再拼接

// fd分为普通的fd，listensockfd
// 我们像让对fd的处理，采用同一种方式
class Reactor;

// 描述一个连接
class Connection
{
public:
    Connection() : _sockfd(-1), _events(0)
    {
        
    }
    // 回调方法
    virtual void Recver() = 0;   // 接收数据的回调方法
    virtual void Sender() = 0;   // 发送数据的回调方法
    virtual void Excepter() = 0; // 异常处理的回调方法
    // 设置客户端信息
    void SetPeerInfo(const InetAddr &addr)
    {
        _peer_addr = addr;
    }
    void SetSockfd(int sockfd)
    {
        _sockfd = sockfd;
    }
    int SockFd() const
    {
        return _sockfd;
    }
    void SetEvents(uint32_t events)
    {
        _events = events;
    }
    uint32_t GetEvents() const
    {
        return _events;
    }
    void SetOwner(Reactor *owner)
    {
        _owner = owner;
    }
    Reactor *GetOwner()
    {
        return _owner;
    }
    void AppendString(const std::string &in)
    {
        _inbuffer += in; // 把收到的数据添加到自己的接收缓冲区
    }
    void AppendToOut(const std::string &out)
    {
        _outbuffer += out; // 把要发送的数据添加到自己的发送缓冲区
    }
    void DisacrdOutString(int n)
    {
        _outbuffer.erase(0, n); // 把发送缓冲区的前n个字节删除
    }
    bool IsOutBufferEmpty()
    {
        return _outbuffer.empty();
    }
    std::string &OutString() // 故意引用返回
    {
        return _outbuffer;
    }
    std::string &InBuffer() // 故意引用返回
    {
        return _inbuffer;
    }
    void Close()
    {
        if(_sockfd >= 0)
        {
            close(_sockfd);
        }
    }
    virtual ~Connection()
    {
    }

protected:
    int _sockfd;
    // 充当应用层的输入缓冲区
    std::string _inbuffer;
    // 充当应用层的输出缓冲区
    std::string _outbuffer;
    InetAddr _peer_addr; // 这个连接对应哪一个客户端

    // 添加一个指针
    // Connection属于哪一个服务器，回指向它
    Reactor *_owner;
    // 该文件描述符关心的事件
    uint32_t _events;
    
    // lastmodtime
    uint64_t _timestamp; 
};

// class Factory
// {
// public:
//     static std::shared_ptr<Connection> BuildConnection(int sockfd, uint32_t events, func_t r, func_t s, func_t e)
//     {
//         auto conn = std::make_shared<Connection>(sockfd);
//         conn->SetEvents(events);
//         conn->InitCB(r, s, e);
//         return conn;
//     }
// };